<?
/**
 * This file is part of XNAT light.
 *
 * XNAT light is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * XNAT light is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XNAT light.  If not, see <http://www.gnu.org/licenses/>.
 */
namespace NRG\Xnat;

use NRG\Exceptions as Exceptions;
use NRG\Framework as Framework;
use NRG\Database\Mappers as Mappers;

/**
 * XNAT subject model
 *
 * @package NRG\Xnat
 */
class Subject extends XObject
{
    /**
     * Subject ID
     *
     * @var string
     */
    protected $_id;
 
    /**
     * Subject label
     *
     * @var label
     */
    protected $_label;

    /**
     * Parent project name
     *
     * @var string
     */
    protected $_projectName;
    
    /**
     * Parent project
     *
     * @var NRG\Xnat\Project
     */
    protected $_project;

    /**
     * Experiments
     *
     * @var array NRG\Xnat\XObject
     */
    protected $_experiments;

    /**
     * Constructor
     */
    public function __construct()
    {
	parent::__construct();

	$this->_experiments = array();
    }

    /**
     * Set subject accession ID
     *
     * @param string $id
     */
    public function setID($id=null)
    {
	if(!is_string($id))
	    throw new Framework\Exceptions\IllegalArgumentException("Accession ID must be a string");

	if($id == "")
	    throw new Framework\Exceptions\IllegalArgumentException("Accession ID cannot be null");

	$this->_id = $id;
    }

    /**
     * Access subject accession ID 
     *
     * @return string
     */
    public function getID()
    {
	return $this->_id;
    }

    /**
     * Set subject label
     *
     * @param string $label
     */
    public function setLabel($label)
    {
	if(!is_string($label))
	    throw new Framework\Exceptions\IllegalArgumentException("Subject label must be a string");

	$label = trim($label);
	
	if($label == "")
	    throw new Framework\Exceptions\IllegalArgumentException("Subject label cannot be empty");

	$this->_label = $label;
    }

    /**
     * Access subject label
     *
     * @return string
     */
    public function getLabel()
    {
	return $this->_label;
    }

    /**
     * Add an experiment
     *
     * @param string $key
     * @param NRG\Xnat\XObject $experiment
     */
    public function addExperiment($key, XObject $experiment=null)
    {
	if(!is_string($key))
	    throw new Framework\Exceptions\IllegalArgumentException("Key must be a string");

	$key = trim($key);

	if($key == "")
	    throw new Framework\Exceptions\IllegalArgumentException("Key cannot be empty");

	$this->_experiments[$key] = $experiment;
    }

    /**
     * Access an experiment by key
     *
     * @param string $key
     * @return NRG\Xnat\XObject
     */
    public function getExperiment($key)
    {
	if(!is_string($key))
	    throw new Framework\Exceptions\IllegalArgumentException("Key must be a string");

	$key = trim($key);
	
	if($key == "")
	    throw new Framework\Exceptions\IllegalArgumentException("Key cannot be empty");

	if(array_key_exists($key, $this->_experiments))
	{
	    if($this->_experiments[$key] === null)
	    {
		$mapper = new Mappers\MrSession();
		$this->_experiments[$key] = $mapper->byId($key);
	    }

	    return $this->_experiments[$key];
	}
	else
	    throw new Framework\Exceptions\IndexOutOfBoundsException($key);
    }

    /**
     * Access all experiments
     *
     * @return array (\NRG\Xnat\Experiment)
     */
    public function getExperiments()
    {
	foreach($this->_experiments as $key => $experiment)
	{
	    if($experiment === null)
		$this->getExperiment($key);
	}

	return $this->_experiments;
    }

    /**
     * Set project name
     *
     * @param string $name
     * @throws IllegalArgumentException
     */
    public function setProjectName($name)
    {
	if(!is_string($name))
	    throw new Framework\Exceptions\IllegalArgumentException("Project name must be a string");

	$name = trim($name);
	
	if($name == "")
	    throw new Framework\Exceptions\IllegalArgumentException("Project name cannot be empty");

	$this->_projectName = $name;
    }

    /**
     * Access parent project
     *
     * @return NRG\Xnat\Project
     * @throws NRG\Exceptions\FieldNotSetException
     */
    public function getProject()
    {
	if($this->_project === null)
	{
	    if($this->_projectName === null)
		throw new Framework\Exceptions\FieldNotSetException("project name");

	    $mapper = new Mappers\Project();
	    $this->_project = $mapper->byId($this->_projectName);
	}

	return $this->_project;
    }

    /**
     * Access parent project name
     *
     * @return string
     */
    public function getProjectName()
    {
	return $this->_projectName;
    }

    /**
     * Access all experiment IDs
     * 
     * @return array (int, string)
     */
    public function getExperimentIDs()
    {
	return array_keys($this->_experiments);
    }
}
